<?php
require_once 'Zend/Service/Abstract.php';

/**
 * Provides a client for consuming Asirra (Animal Species
 * Image Recognition for Restricting Access) service, CAPTCHA
 * alternative which works by asking users to identify
 * photographs of cats and dogs.
 *
 * @author Nikola Posa <posa.nikola@gmail.com>
 * @license http://opensource.org/licenses/gpl-3.0.html GNU General Public License
 */
class NP_Service_Asirra extends Zend_Service_Abstract
{
    const API_SERVER = 'http://challenge.asirra.com';

    /**
     * Options for customizing the look of the Asirra challenge.
     * 
     * @var array
     */
    protected $_options = array(
        'enlargedPosition'=>'top',
        'cellsPerRow'=>6
    );

    /**
     * Constructor.
     *
     * @return void
     */
    public function  __construct($options = null)
    {
        if ($options != null) {
            if ($options instanceof Zend_Config) {
                $options = $options->toArray();
            }

            if (!is_array($options)) {
                require_once 'NP/Service/Asirra/Exception.php';
                throw new NP_Service_Asirra_Exception('Options must be an array or instance of Zend_Config');
            }

            $this->setOptions($options);
        }
    }

    //PUBLIC ONLY FOR UNIT TESTS
    public static function resetHttpClient()
    {
        self::$_httpClient = null;
    }
    
    /**
     * Sets single Asirra option.
     *
     * @param string $name
     * @param mixed $value
     * @return NP_Service_Asirra
     */
    public function setOption($name, $value)
    {
        if (array_key_exists($name, $this->_options)) {
            $this->_options[$name] = $value;
        }

        return $this;
    }

    /**
     * Sets Asirra options.
     * 
     * @param array $options
     * @return NP_Service_Asirra
     */
    public function setOptions(array $options)
    {
        foreach ($options as $name => $value) {
            $this->setOption($name, $value);
        }

        return $this;
    }

    /**
     * Gets Asirra options.
     *
     * @param string $key Name of some specific option whose value will be retrieved. (optional)
     * @return mixed
     */
    public function getOptions($key = null)
    {
        if ($key != null && array_key_exists($key, $this->_options)) {
            return $this->_options[$key];
        }

        return $this->_options;
    }

    /**
     * Generates and returns Asirra HTML code.
     * 
     * @return string
     */
    public function getHtml()
    {
        $retval = '
<script type="text/javascript" src="' . self::API_SERVER . '/js/AsirraClientSide.js"></script>';

        $retval .= '
<script type="text/javascript">';
        foreach ($this->_options as $key=>$value) {
            $quotes = (is_string($value)) ? '"' : '';
            $retval .= '
    asirraState.Set' . ucfirst($key) . '(' . $quotes . $value . $quotes . ');';
        }
        $retval .= '
</script>';

        return $retval;
    }

    /**
     * Validates Asirra ticket.
     *
     * @param string $ticket
     * @return NP_Service_Asirra_Response
     */
    public function verify($ticket)
    {
        if (empty($ticket)) {
            require_once 'NP/Service/Asirra/Exception.php';
            throw new NP_Service_Asirra_Exception('Asirra ticket is missing.');
        }

        $httpClient = self::getHttpClient();

        $params = array(
            'action' => 'ValidateTicket',
            'ticket' => $ticket
        );

        $response = $httpClient->setMethod(Zend_Http_Client::GET)
              ->setUri(self::API_SERVER . '/cgi/Asirra')
              ->setParameterGet($params)
              ->request();

        require_once 'NP/Service/Asirra/Response.php';
        return NP_Service_Asirra_Response::fromHttpResponse($response);
    }
}